import {
  ui
} from "../../tools/ui";
import {
  checkTool
} from "../../tools/check";
import {
  dsx
} from "../../tools/datax";
import {
  pages
} from "../../tools/pages";
import {
  resource
} from "../../static/resource";
import {
  nav2
} from "../../tools/nav2";


const config = {
  CONTENT_LENGTH: 20,
  MSG_RECEIVER_TIMEOUT: 1500
}
const emptyPromise = new Promise((resolve, reject) => {
  resolve({})
})

const _ = dsx.cmd,
  $ = _.aggregate

Page({
  data: {
    resource,
    enable: false,
    showMediaPanel: false,
    textMsg: '',
    chat: {
      contents: []
    },
    user: {},
    autoScroll: true,
    scrollTop: -1,
    enableRefresher: true,
    fromTime: 0,
    toTime: 0,
    noMoreMsg: false,
    svHeight: "",
    enableAutoScroll2Bottom: true,
    sessionOpenId: null,
    canUseMediaPanel: false,
    fastReply: null
  },
  async onLoad(options) {
    this.timers = []
    ui.loading()
    this.parseOptions(options)
    this.adjustSVHeight()
    await this.loadUser()
    await this.loadChat(options) // sessionOpenId
    await this.processFromSession(options)
    this.scrollContent2Bottom()
    this.buildMsgReceiver()
    ui.loading(false)
  },
  async processFromSession(options) {
    const {
      from,
      goodsId, // send goods msg
      title,
      showTicket,
      orderId, // send order msg
      shopName,
      ticket
    } = options
    if (from == 'goodsDetail') {
      await this.sendGoodsMsg(goodsId, title + "（自动发送，来源：商品详情）", showTicket)
    } else if (from == 'orderDetail') {
      await this.sendOrderMsg(orderId, shopName, '（自动发送，来源：订单详情）', ticket)
    }
  },
  clearTimers() {
    for (const timer of this.timers) {
      clearTimeout(timer)
    }
    this.timers = []
  },
  parseOptions(options) {
    const {
      sessionOpenId,
      userId
    } = options
    if (sessionOpenId) this.setData({
      sessionOpenId
    })
    if (userId) this.setData({
      userId
    })
  },
  adjustSVHeight() {
    this.setData({
      svHeight: wx.getSystemInfoSync().windowHeight - ui.rpx2px(110)
    })
  },
  async loadUser() {
    await dsx.cloudGetByOpenid('users').then(res => { // todo get and init
      const user = res.result.data[0]
      const {
        sessionOpenId
      } = this.data
      this.setData({
        user,
        sessionOpenId: sessionOpenId ? sessionOpenId : user._openid,
        canUseMediaPanel: ['admin', 'delivery', 'master'].indexOf(user.role) >= 0
      })
    })
  },
  loadChat(param) { // { latestTime, source: 'renew' | 'refresher' }
    if (this.pauseChat) return emptyPromise
    const {
      sessionOpenId,
      userId,
      chat,
    } = this.data
    const {
      latestTime
    } = param || {}
    const source = param?.source || 'refresher'
    // console.log(latestTime, source)
    let projectObj = {}
    if (source == 'refresher') {
      projectObj = {
        _id: 1,
        _openid: 1,
        sessionOpenId: 1,
        contents: chat.contents.length == 0 ? $.slice(['$contents', -config.CONTENT_LENGTH]) : $.slice(['$contents', -(chat.contents.length + config.CONTENT_LENGTH), config.CONTENT_LENGTH]),
      }
    } else {
      projectObj = {
        _id: 1,
        _openid: 1,
        sessionOpenId: 1,
        contents: latestTime ? ($.filter({
          input: '$contents',
          as: 'item',
          cond: $.gt(['$$item.time', latestTime])
        })) : 1
      }
    }
    return dsx.coll('chat')
      .aggregate()
      .match({
        sessionOpenId: _.eq(sessionOpenId)
      })
      .project(projectObj)
      .end()
      .then(async res => {
        if (res.list.length == 0) return await this.makeChat(sessionOpenId, userId)

        const chat = res.list[0]
        this.setReadStat(chat)
        await this.prepareChat(source, chat)
        ui.loading(false)
      })
  },
  makeChat(sessionOpenId, userId) {
    const user = this.data.user
    return dsx.cloudUpdate('chat', null, {
      userId: userId ? _.eq(userId) : _.exists(true),
      sessionOpenId: userId ? _.exists(true) : _.eq(sessionOpenId || user._openid)
    }).then(res => {
      // console.log('makeChat', user, res)
      res.result?._id && this.setData({
        chat: {
          _id: res.result._id,
          userId: user._id
        }
      })
      ui.loading(false)
    })
  },
  setReadStat(chat) {
    if (!chat.contents || chat.contents.length == 0) return
    const latestMsg = chat.contents[chat.contents.length - 1],
      latestTime = this.latestTimeOfLoadedChat()
    // console.log(chat.sessionOpenId, user._id, latestMsg.time)
    if (latestTime && latestMsg.time <= latestTime) return

    dsx.cloudUpdateWhere('chat', {
      sessionOpenId: chat.sessionOpenId
    }, {
      read: {
        [`${this.data.user._id}`]: latestMsg.time
      }
    })
  },
  async prepareChat(source, gotChat) {
    const {
      user,
      chat,
      noMoreMsg,
      sessionOpenId
    } = this.data
    chat._id = chat._id || gotChat._id
    chat.sessionOpenId = chat.sessionOpenId || gotChat.sessionOpenId
    chat.users = chat.users || {}
    chat.contents = chat.contents || []
    gotChat.users = {
      [`${user._id}`]: user
    }
    // console.log(gotChat.contents)
    const newContents = []
    for (const content of gotChat.contents || []) {
      if (chat.contents.find(ele => ele.time == content.time)) continue

      newContents.push(content)
      if (user._openid == sessionOpenId) {
        content.position = (content.userOpenId == user._openid ? 'right' : 'left')
      } else {
        content.position = (content.userOpenId == sessionOpenId ? 'left' : 'right')
      }

      if (chat.users[content.userId]) continue
      await dsx.coll('users').where({
          _id: content.userId
        })
        .get()
        .then(res => {
          const u = res.data[0]
          if (u) chat.users[u._id] = u
        })
    }
    // console.log(newContents.length)
    if (source == 'refresher') {
      chat.contents = newContents.concat(chat.contents)
    } else {
      chat.contents = chat.contents.concat(newContents)
    }

    this.setData({
      chat,
      noMoreMsg: noMoreMsg ? true : (source == 'refresher' && newContents.length < config.CONTENT_LENGTH)
    })
    if (newContents.length > 0) this.autoScroll2Bottom()
  },
  scrollContent2Bottom() {
    let that = this;
    wx.nextTick(() => {
      this.scrollCmd = 'toBottom'
      that.setData({
        scrollTop: 1 // triggers onSVScroll
      });
    })
  },
  onSVScroll(e) {
    const {
      detail
    } = e
    const {
      svHeight
    } = this.data
    if (this.scrollCmd == "toBottom") {
      this.setData({
        scrollTop: detail.scrollHeight - svHeight
      })
      this.scrollCmd = null
    }

    this.setData({
      enableAutoScroll2Bottom: detail.scrollHeight - svHeight - detail.scrollTop < 200
    })
  },
  handleRefresher() {
    ui.loading()
    this.loadChat()
    this.setData({
      enableRefresher: false
    })
  },

  addMediaTap() {
    const {
      showMediaPanel
    } = this.data
    this.setData({
      showMediaPanel: !showMediaPanel
    })
  },
  addPicTap() { // 添加图片
    wx.navigateTo({
      url: '/pages/common/imgSelect/index?action=select',
    })
  },
  imgSelected(files, tag) {
    if (files && files.length > 0) {
      this.sendMsg({
        msg: {
          src: files[0]
        },
        msgType: 'image'
      })
    }
  },
  goToGoodsTap() {
    wx.navigateTo({
      url: `/pages/common/goodsManage/index?action=select&visible=true`,
    })
  },
  goodsSelected(goods, option) {
    // console.log(goods, option)
    if (!goods || !option) return
    this.sendGoodsMsg(goods.id, goods.title, option.ticket)
  },
  sendGoodsMsg(id, title, showTicket) {
    this.sendMsg({
      msg: {
        id,
        title
      },
      msgType: showTicket ? 'ticket' : 'goods',
    })
  },
  sendOrderMsg(id, shopName, title, ticket) {
    this.sendMsg({
      msg: {
        id,
        shopName,
        title,
        ticket: JSON.parse(ticket || false)
      },
      msgType: 'order',
    })
  },
  goToTicketTap() {
    wx.navigateTo({
      url: `/pages/common/goodsManage/index?action=select&ticket=true`,
    })
  },
  onGoodsTap(e) {
    const id = ui.eventData(e, 'id'),
      type = ui.eventData(e, 'msgtype')
    wx.navigateTo({
      url: `/pages/goods/details/index?id=${id}&showTicket=${type=='ticket'}`,
    })
  },
  onOrderTap(e) {
    const sessionOpenId = this.data.sessionOpenId,
      user = this.data.user
    const item = ui.eventData(e, 'item'),
      id = item.id,
      search = JSON.stringify({
        orderId: id
      })
    if (item.userOpenId == sessionOpenId && sessionOpenId == user._openid) nav2.orderList('myOrder', item.ticket, search)
    else if (['admin', 'master'].indexOf(user.role) >= 0) nav2.orderList('manage', item.ticket, search)
  },
  goToOrderTap(e) {
    const {
      sessionOpenId
    } = this.data
    const search = JSON.stringify({
      openId: sessionOpenId,
    })
    wx.navigateTo({
      url: `/pages/order/order-list/index?search=${search}&action=search`,
    })
  },
  checkTicketTap(e) {
    const {
      sessionOpenId
    } = this.data
    const search = JSON.stringify({
      openId: sessionOpenId,
      ticket: true
    })
    wx.navigateTo({
      url: `/pages/order/order-list/index?search=${search}&ticket=true&action=search`,
    })
  },
  async fastReplyTap() {
    if (!this.data.fastReply) await this.loadFastReply()
    const {
      list
    } = this.data.fastReply
    const sheets = {}
    for (let index in list) {
      sheets[index] = list[index].title
    }
    ui.actionSheet(sheets, async (desc, key) => {
      const contents = list[key].contents
      for (const content of contents) {
        // console.log(content)
        await this.sendMsg({
          msg: {
            ...content,
            msgTypeDesc: undefined
          },
          msgType: content.msgType
        })
      }
    })
  },
  async loadFastReply() {
    ui.loading()
    const res = await dsx.coll('setting')
      .limit(1)
      .get()
    this.setData({
      fastReply: res.data[0].fastReply
    })
    ui.loading(false)
  },
  onMsgInput(e) {
    const msg = e.detail.value
    this.textMsg = msg
    this.setData({
      textMsg: msg
    })
  },
  onAvatarTap(e) {
    const {
      user
    } = this.data
    const userId = ui.eventData(e, 'userid')

    if (user.role == 'admin') {
      wx.navigateTo({
        url: `/pages/usercenter/staff/edit/index?id=${userId}&action=edit`,
      })
    } else
    if (['master', 'delivery', 'staff'].indexOf(this.data.user.role) >= 0) {
      wx.navigateTo({
        url: `/pages/usercenter/staff/edit/index?id=${userId}`,
      })
    }
  },
  async sendTap() {
    const {
      sending
    } = this.data
    if (sending) {
      ui.toast('发送速度过快')
      return
    }
    this.setData({
      textMsg: ''
    })
    this.sendMsg({
      msg: {
        text: this.textMsg
      }
    })
  },
  sendMsg({
    msg,
    msgType
  }) {
    const {
      chat,
      user
    } = this.data
    // console.log(chat)
    msgType = msgType || 'text'
    if (msgType == 'text') {
      checkTool.check([{
        value: msg.text,
        title: '消息'
      }])
    }

    if (this.sending) return {}
    this.sending = true

    const time = new Date().getTime()
    const content = {
      ...msg,
      msgType,
      time,
      userId: user._id,
      userOpenId: user._openid
    }
    this.prepareChat('send', {
      _id: chat._id,
      sessionOpenId: user._openid,
      contents: [content]
    })
    this.autoScroll2Bottom()
    // console.log(chat)
    return wx.cloud.callFunction({
      name: 'chatCmd',
      data: {
        cmd: 'putMsg',
        chatId: chat._id,
        content: {
          ...content,
          position: undefined
        }
      }
    }).then(res => {
      const success = (res.result.errMsg.endsWith(':ok'));
      if (!success) {
        const errMsg = (chat.contents || []).find(ele => ele.time == content.time)
        errMsg.error = true
      }
      this.sending = false
    })
  },
  pushToContent(data) {

  },
  onRefresh() {
    this.setData({
      enable: true
    });
    setTimeout(() => {
      this.setData({
        enable: false
      });
    }, 1500);
  },
  onScroll(e) {
    // const {
    //   scrollTop
    // } = e.detail;

    // this.setData({
    //   backTopVisible: scrollTop > 100,
    // });
  },
  buildMsgReceiver(env) {
    const that = env || this
    const timerId = setTimeout(() => {
      // console.log(chat)
      that.loadChat({
        latestTime: that.latestTimeOfLoadedChat(),
        source: 'renew',
      }).then(res => {
        // console.log(res)
        if (res?.list?.length > 0 && res?.list[0]?.contents?.length > 0) that.autoScroll2Bottom()
        ui.loading(false)
        const timerId = setTimeout(() => that.buildMsgReceiver(), config.MSG_RECEIVER_TIMEOUT);
        that.timers.push(timerId)
      })
    }, config.MSG_RECEIVER_TIMEOUT);
    this.timers.push(timerId)
  },
  latestTimeOfLoadedChat() {
    const chat = this.data.chat
    return (chat.contents?.length > 0 ? chat.contents.slice(-1)[0].time : undefined)
  },
  autoScroll2Bottom() {
    const {
      enableAutoScroll2Bottom
    } = this.data

    if (enableAutoScroll2Bottom) {
      this.scrollContent2Bottom()
    }
  },
  onUnload() {
    this.clearTimers()
    const prePage = pages.previous()
    prePage?.backFromChatSession && prePage.backFromChatSession()
  },
  onHide() {
    this.pauseChat = true
  },
  onShow() {
    this.pauseChat = false
  }
})